<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #canvas,
        #cvs_scale {
            border: solid 1px #000;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
    </style>
</head>

<body>
    <canvas width="800" height="500" id="cvs_scale"></canvas>
    <canvas width="800" height="500" id="canvas"></canvas>
    <script>
        var height = 500, width = 800;// 画布大小
        var scaleX = 40, scaleY = 225;// 刻度宽度
        var data = [
            { x: 0, y: 0 },
            { x: 1, y: 0.03 },
            { x: 2, y: 0.08 },
            { x: 3, y: 0.1 },
            { x: 4, y: 0.16 },
            { x: 5, y: 0.24 },
            { x: 6, y: 0.35 },
            { x: 7, y: 0.69 },
            { x: 8, y: 0.95 },
        ]
        var cvs = document.getElementById('cvs_scale');
        cvs.style.height = height;
        cvs.style.width = width;
        var ctx_scale = cvs.getContext('2d');
        drawAxis();

        var canvas = document.getElementById('canvas');
        var percent = 0;
        canvas.style.height = height;
        canvas.style.width = width;
        var ctx = canvas.getContext('2d');
        // drawAnimation();

        // 初始化图表
        function initChart() {

        }

        // 绘制坐标
        function drawAxis() {
            drawLine(ctx_scale, { x: 20, y: 20 }, { x: 20, y: 450 }, "black");
            drawLine(ctx_scale, { x: 20, y: 20 }, { x: 660, y: 20 }, "black");
            for (let i = 0; i < 8; i++) {
                ctx_scale.fillText(i * 2, scaleX * i * 2 + 20, height - 10)
            }
            ctx_scale.fillText('1x', 5, height - 20 - scaleY)
        }

        // 绘制直线
        function drawLine(ctx, start, end, color) {
            ctx.beginPath();
            ctx.moveTo(start.x, height - start.y);
            ctx.lineTo(end.x, height - end.y);
            ctx.strokeStyle = color;
            ctx.stroke();
            ctx.closePath()
        }

        // 绘制刻度文字
        function drawScale() {

        }

        // 
        function draw(ctx, start, percent) {
            ctx.clearRect(0, 0, 800, 500)
            ctx.moveTo(start.x * scaleX + 20, height - start.y * scaleY - 20)
            // ctx_scale.fillText(start.x,start.x*scaleX+20,height-10)
            let endPointX = 0;
            for (var i = 1; i < percent; i++) {
                var x = data[i].x * scaleX + 20;
                var y = data[i].y * scaleY - 20;
                ctx.lineTo(x, height - y)
                /* if(scaleX < 20){
                    if(i%5===0){
                        ctx_scale.fillText(data[i].x,x,height-10)
                    }
                }else{
                    ctx_scale.fillText(data[i].x,x,height-10)
                } */
                if (data[i].y > 2) {
                    clear()
                    scaleY = 450 / data[i].y
                    ctx_scale.fillText('2x', 5, height - 20 - scaleY * 2)
                }
                endPointX = x;
            }
            ctx.lineTo(x, height - 20)
            ctx.strokeStyle = 'rgb(194,197,242)'
            // ctx.closePath()
            drawAreaColor()
            // ctx.fill();
            // ctx.fillStyle = 'lightblue'
        }

        // 绘制图表动画
        function drawAnimation() {
            // ctx.clearRect(0,0,800,500);
            clear()
            ctx.beginPath();
            draw(ctx, { x: 0, y: 0 }, percent);
            ctx.stroke();

            percent = percent + 1;
            if (percent > data.length) {
                data.push({ x: percent - 1, y: Math.random() * 1 })
                scaleX = 660 / data.length
            }
            if (percent > 55) {
                ctx.closePath()
                return
            }
            requestAnimationFrame(drawAnimation)
        }

        // 绘制线性图表颜色填充
        function drawAreaColor(startColor, endColor) {
            var grd = ctx.createLinearGradient(0, 0, 0, 170);
            grd.addColorStop(0, "rgba(194,197,242,.2)");
            grd.addColorStop(1, "rgba(194,197,242,.2)")
            ctx.fillStyle = grd;
            ctx.fill()
        }

        function clear() {
            ctx_scale.clearRect(0, 0, 800, 500)
            drawAxis()
        }

        function toParseData(data,scaleX,scaleY){
            for(let i = 0; i < data.length; i++){
                data[i].x = data[i].x * scaleX + 20;
                data[i].y = height - data[i].y * scaleY - 20;
            }
            return data
        }
        /* 
         * 1.分别求出两方向的单位向量，n=AB/|AB|
         * 
         */
        var points = [{ x: 50, y: 50 }, { x: 200, y: 100 }, { x: 250, y: 50 }, { x: 350, y: 150 }, { x: 370, y: 100 }, { x: 570, y: 200 }];
        ctx.strokeStyle = "#ccc";
        ctx.lineWidth = 3;
        drawPath(toParseData(data,scaleX,scaleY),ctx,percent);
        function drawPath(path, ctx, percent) {
            var Vector2 = function (x, y) {
                this.x = x;
                this.y = y;
            };
            Vector2.prototype = {
                "length": function () {
                    return Math.sqrt(this.x * this.x + this.y * this.y);
                },
                "normalize": function () {
                    var inv = 1 / this.length();
                    return new Vector2(this.x * inv, this.y * inv);
                },
                "add": function (v) {
                    return new Vector2(this.x + v.x, this.y + v.y);
                },
                "multiply": function (f) {
                    return new Vector2(this.x * f, this.y * f);
                },
                "dot": function (v) {
                    return this.x * v.x + this.y * v.y;
                },
                "angle": function (v) {
                    return Math.acos(this.dot(v) / (this.length() * v.length())) * 180 / Math.PI;
                }
            };
            function getControlPoint(path) {
                ctx.clearRect(0,0,800,500)
                var rt = 0.3;
                var i = 0, count = path.length - 2;
                var arr = [];
                for (; i < count; i++) {
                    var a = path[i], b = path[i + 1], c = path[i + 2];
                    var v1 = new Vector2(a.x - b.x, a.y - b.y);
                    var v2 = new Vector2(c.x - b.x, c.y - b.y);
                    var v1Len = v1.length(), v2Len = v2.length();
                    var centerV = v1.normalize().add(v2.normalize()).normalize();
                    var ncp1 = new Vector2(centerV.y, centerV.x * -1);
                    var ncp2 = new Vector2(centerV.y * -1, centerV.x);
                    if (ncp1.angle(v1) < 90) {
                        var p1 = ncp1.multiply(v1Len * rt).add(b);
                        var p2 = ncp2.multiply(v2Len * rt).add(b);
                        arr.push(p1, p2)
                    }
                    else {
                        var p1 = ncp1.multiply(v2Len * rt).add(b);
                        var p2 = ncp2.multiply(v1Len * rt).add(b);
                        arr.push(p2, p1)
                    }
                }
                return arr;
            }

            var point = getControlPoint(path);
            console.log(point);
            var points = path;
            ctx.beginPath();
            var int = 0;
            for (var i = 0; i < points.length; i++) {
                if (i == 0) {
                    ctx.moveTo(points[0].x, points[0].y);
                    ctx.quadraticCurveTo(point[0].x, point[0].y, points[1].x, points[1].y);
                    int = int + 1;
                }
                else if (i < points.length - 2) {
                    ctx.moveTo(points[i].x, points[i].y);
                    ctx.bezierCurveTo(point[int].x, point[int].y, point[int + 1].x, point[int + 1].y, points[i + 1].x, points[i + 1].y);
                    int += 2;
                }
                else if (i == points.length - 2) {
                    ctx.moveTo(points[points.length - 2].x, points[points.length - 2].y);
                    ctx.quadraticCurveTo(point[point.length - 1].x, point[point.length - 1].y, points[points.length - 1].x, points[points.length - 1].y);
                }

            }
            ctx.stroke();
            ctx.closePath();

            ctx.beginPath();
            ctx.arc(points[points.length-1].x, points[points.length-1].y, 5, 0, 2 * Math.PI);
            ctx.fillStyle = "#cccccc";
            ctx.fill();
            ctx.closePath();

            /* for (i = 0; i < points.length; i++) {
                ctx.beginPath();
                ctx.arc(points[i].x, points[i].y, 5, 0, 2 * Math.PI);
                ctx.fillStyle = "#cccccc";
                ctx.fill();
                ctx.closePath();
            } */

        }
    </script>
</body>

</html>